package com.libinshen.wxpay.login.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.libinshen.wxpay.common.constant.Constants;
import com.libinshen.wxpay.common.enums.ErrorCodeConstants;
import com.libinshen.wxpay.common.enums.IsDeletedEnums;
import com.libinshen.wxpay.common.util.ServiceExceptionUtil;
import com.libinshen.wxpay.common.util.common.DateUtils;
import com.libinshen.wxpay.common.util.common.IpUtil;
import com.libinshen.wxpay.common.util.common.JwtUtils;
import com.libinshen.wxpay.login.entity.SoftWareInfo;
import com.libinshen.wxpay.login.entity.miniapp.AppAuthLoginRespVO;
import com.libinshen.wxpay.login.entity.miniapp.AuthLoginReqVO;
import com.libinshen.wxpay.login.mapper.SoftWareMapper;
import com.libinshen.wxpay.login.mapper.TokenMapper;
import com.libinshen.wxpay.login.mapper.UserInfoMapper;
import com.libinshen.wxpay.login.service.AccountService;
import com.libinshen.wxpay.login.service.UserInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service("userService")
@Slf4j
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, AuthLoginReqVO> implements UserInfoService {


    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private UserInfoMapper userMapper;

    @Resource
    private TokenMapper tokenMapper;

    @Resource
    private SoftWareMapper softWareMapper;

    @Resource
    private AccountService accountService;

    @Override
    public AppAuthLoginRespVO register(AuthLoginReqVO authLoginReqVO, HttpServletRequest request) {
        AppAuthLoginRespVO appAuthLoginRespVO = new AppAuthLoginRespVO();
////        if (StringUtils.isEmpty(authLoginReqVO.getUserName())) {
////            throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_LOGIN_BAD_CREDENTIALS);
////        }
////
////        if (StringUtils.isEmpty(authLoginReqVO.getPassword())) {
////
////        }
//
//        //验证身份证信息是否正确
//        if (!CheckIdCardUtils.check(authLoginReqVO.getIdentityCard())) {
//            return CommonResult.error().setMessage("您身份证不正确，请重新输入！");
//        }
//
//        //验证手机号格式是否正确
//        if (!PhoneFormatCheckUtils.isChinaPhoneLegal(authLoginReqVO.getPhone())) {
//            return CommonResult.error().setMessage("您输入的手机号格式不正确，请重新输入！");
//        }
//        //验证出生年月是否正确
//        if (!DateUtils.validBirthday(authLoginReqVO.getBirthday())) {
//            return CommonResult.error().setMessage("您输入的出生日期格式不正确，请重新输入！");
//        }

        authLoginReqVO.setCreateTime(DateUtils.getDateMonth());
        authLoginReqVO.setRegisteredIp(IpUtil.getIpAddr(request));
        AppAuthLoginRespVO userByName = userMapper.getUserByName(authLoginReqVO.getUserName());

        if (!StringUtils.isEmpty(userByName)) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_LOGIN_BAD_CREDENTIALS);
        }

        //我们是用Spring Security中的密码加密工具
        authLoginReqVO.setPassword(passwordEncoder.encode(authLoginReqVO.getPassword()));
        userMapper.register(authLoginReqVO);

        return appAuthLoginRespVO;
    }

    @Override
    public AppAuthLoginRespVO login(AuthLoginReqVO user) {

//        if (StringUtils.isEmpty(user.getUserName())) {
//            return CommonResult.error().setMessage("用户名不能为空，请重新输入！");
//        }
//
//        if (StringUtils.isEmpty(user.getOrignPassword())) {
//            return CommonResult.error().setMessage("密码不能为空，请重新输入！");
//        }

        AppAuthLoginRespVO appAuthLoginRespVO = userMapper.getUserByName(user.getUserName());
        if (appAuthLoginRespVO == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_LOGIN_BAD_CREDENTIALS);
        }

        if (IsDeletedEnums.NODELETED.getCode().equals(appAuthLoginRespVO.getIsDeleted())) {
            //已删除的用户，如果注销时间超过7天，就将用户锁定
            long days = DateUtils.pastDays(new Date(appAuthLoginRespVO.getCreateTime()));
            if (days > Constants.SEVEN) {
                //TODO return CommonResult.error().setMessage("用户已锁定");
            }
        }

        //校验密码是否正确
        /***
         *  第一个是未加密的密码
         *   第二个是加密密码；来自于数据库
         */
        boolean matches = passwordEncoder.matches(user.getPassword(), appAuthLoginRespVO.getPassword());
        if (!matches) {
            //TODO return CommonResult.error().setMessage("密码不正确，请重新输入！");
        }

        //密码验证成功，去redis 中查看是否有token 信息。如果有就返回给前端，如果没有就新创建一个存入redis。
        String redisTokenKey = Constants.PERMISSION_WEB_USER_INFO + appAuthLoginRespVO.getId();
        String token = redisTemplate.opsForValue().get(redisTokenKey);
        if (StringUtils.isEmpty(token)) {
            //token过期自动删除或者第一次登陆
            token = JwtUtils.creatToken(Long.valueOf(appAuthLoginRespVO.getId()), new Date());
            //token 在redis的存储时间是12 Hours
            redisTemplate.opsForValue().set(redisTokenKey, token, 12, TimeUnit.HOURS);
        }

        appAuthLoginRespVO.setAccessToken(token);
        return appAuthLoginRespVO;
    }

    @Override
    public void signOut(Long userId) {
        //todo 用户退出功能，暂时的流程是：删除用户在redis中的token
        //获取当前登陆的用户id
        String redisTokenKey = Constants.PERMISSION_WEB_USER_INFO + userId;
        redisTemplate.delete(redisTokenKey);
    }

    ////在登陆的时候，判断用户删除的时间和登录时间进行对比，如果超过7天就将用户数据删除
    @Override
    public void logOut(AuthLoginReqVO authLoginReqVO) {
        authLoginReqVO.setIsBlocked(IsDeletedEnums.NODELETED.getCode());
        authLoginReqVO.setLoginTime(DateUtils.getCommonDate());
        baseMapper.updateById(authLoginReqVO);
    }


    /**
     * 根据用户手机的设备号，对软件进行锁定功能。即一个软件在一个手机上被锁定，将永久不能在该手机上使用
     */
    @Override
    public void lockSoftWare(AuthLoginReqVO authLoginReqVO) {
        authLoginReqVO.setIsLogout(IsDeletedEnums.NODELETED.getCode());
        authLoginReqVO.setLoginTime(DateUtils.getCommonDate());
        baseMapper.updateById(authLoginReqVO);
        //在登陆的时候，判断用户删除的时间和登录时间进行对比，如果超过7天就将用户数据删除
    }

    @Override
    public void updateUserInfo(AuthLoginReqVO authLoginReqVO) {

        //根据用户名查询用户是否存在
        AppAuthLoginRespVO appAuthLoginRespVO = userMapper.getUserByName(authLoginReqVO.getUserName());
        if (appAuthLoginRespVO == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.AUTH_LOGIN_BAD_CREDENTIALS);
        }

        //使用spring security对密码进行加密
        authLoginReqVO.setPassword(passwordEncoder.encode(authLoginReqVO.getPassword())); // 加密密码
        userMapper.updateById(authLoginReqVO);
    }


    @Override
    public SoftWareInfo getSoftWareInfomation() {
        QueryWrapper<SoftWareInfo> wrapper = new QueryWrapper<>();
        List<SoftWareInfo> softWareInfos = softWareMapper.selectList(wrapper.eq("id", 1));
        return softWareInfos.get(0);
    }
}
